package simpleTaskDispatcher.model.taskDispatchers;

import java.util.Comparator;

import simpleTaskDispatcher.model.TaskQueue;

public class TaskQueueComparators {

	public static Comparator<TaskQueue> compareByAscCreation() {
		return new AbstractStartedFirstComparator(true) {

			@Override
			public int compareTaskQueues(TaskQueue o1, TaskQueue o2) {
				return o1.getCreation().compareTo(o2.getCreation());
			}
		};

	}
	
	public static Comparator<TaskQueue> compareByDescUnrealisedWorkValue(boolean higherPriorityForStartedQueues, final boolean closedTaskQueuesFirst) {
		return new AbstractStartedFirstComparator(higherPriorityForStartedQueues) {

			@Override
			public int compareTaskQueues(TaskQueue o1, TaskQueue o2) {
				if (closedTaskQueuesFirst) {
					if (o1.isCloseSignaled() && !o2.isCloseSignaled()) {
						return -1;
					} else if (!o1.isCloseSignaled() && o2.isCloseSignaled()) {
						return 1;
					}
				
				}
				return -1 * new Double(o1.getUnrealisedWork()).compareTo(o2.getUnrealisedWork());
			}
		};
	}
	
	public static Comparator<TaskQueue> compareByPriority(boolean higherPriorityForStartedQueues) {
		return new AbstractStartedFirstComparator(higherPriorityForStartedQueues) {

			@Override
			public int compareTaskQueues(TaskQueue o1, TaskQueue o2) {
				return new Integer(o1.getPriority()).compareTo(o2.getPriority());
			}
		};
	}
	
	protected static abstract class AbstractStartedFirstComparator implements Comparator<TaskQueue> {

		private boolean higherPriorityForStartedQueues;
		
		public AbstractStartedFirstComparator() {
			higherPriorityForStartedQueues = true;
		}
		
		public AbstractStartedFirstComparator(boolean higherPriorityForStartedQueues) {
			this.higherPriorityForStartedQueues = higherPriorityForStartedQueues;
		}
		
		@Override
		public int compare(TaskQueue o1, TaskQueue o2) {
			
			if (higherPriorityForStartedQueues) {
			
				boolean o1Started = o1.getPlannedNbWorkers() > 0 || o1.getRealisedWork() > 0;
				boolean o2Started = o2.getPlannedNbWorkers() > 0 || o2.getRealisedWork() > 0 ;
				
				if (o1Started && o2Started) {
					return compareTaskQueues(o1, o2);
				} else if (o1Started && !o2Started) {
					return -1;
				} else if (!o1Started && o2Started) {
					return 1;
				} else {
					return compareTaskQueues(o1, o2);
				}
			} else {
				return compareTaskQueues(o1, o2);
			}
		}
		
		public abstract int compareTaskQueues(TaskQueue o1, TaskQueue o2);
	}
	
	
}
